import * as THREE from 'three'
import * as d3 from 'd3'
import outputFragment from './output_fragment.glsl.js'
import { cylinderObj } from '../cylinder/index.js'
import { createProvinceName } from '../provinceName/index.js'
import { provinceDeviceCount } from '@/api/homePage'

const waterObj = {}
const projection = d3
  .geoMercator()
  .center([107.067641, 36.226277])
  .translate([0, 0])
const cityData = []

// 地图模型侧边材质
const sideMaterial = new THREE.MeshBasicMaterial({
  color: '#00E6E6',
  transparent: true,
  opacity: 1
})

// 侧边材质uniform
let mapUf = {
  uTime: { value: 0.0 },
  uHeight: { value: 10 },
  uColor: { value: new THREE.Color('#00ffff') },
  uStart: { value: -10 },
  uSpeed: { value: 6 }
}

// 渲染前更改材质shader代码
sideMaterial.onBeforeCompile = shader => {
  shader.uniforms = { ...shader.uniforms, ...mapUf }
  shader.vertexShader = shader.vertexShader.replace(
    'void main() {',
    `
      varying vec3 vPosition;
      void main() {
        vPosition = position;
    `
  )
  shader.fragmentShader = shader.fragmentShader.replace(
    'void main() {',
    `
      varying vec3 vPosition;
      uniform float uTime;
      uniform vec3 uColor;
      uniform float uSpeed;
      uniform float uStart;
      uniform float uHeight;
      void main() {
    `
  )
  shader.fragmentShader = shader.fragmentShader.replace(
    'vec3 outgoingLight = reflectedLight.indirectDiffuse;',
    outputFragment
  )
}

// 初始化地图
async function initMap() {
  const url =
    'http://211.143.122.110:18062/mapdata/geojson/areas_v3_full/all/100000.json'
  return await new Promise(resolve => {
    fetch(url)
      .then(response => response.json())
      .then(async data => {
        const waterData = await provinceDeviceCount()
        waterData.data.data.forEach(obj => {
          waterObj[obj['name']] = obj['deviceCount']
        })
        operationData(data, waterObj, resolve)
      })
  })
}

// 解析地图json数据
function operationData(data, waterObj, resolve) {
  const mapModel = new THREE.Group()
  mapModel.rotateX(-Math.PI / 2)
  mapModel.name = '地图模型'

  const features = data.features
  features.forEach((feature, index) => {
    const province = new THREE.Object3D()
    const name = feature.properties.name
    province.name = name
    province.animationActive = false
    mapModel.add(province)

    const provinceLine = new THREE.Object3D()
    provinceLine.name = '省份边界线'
    provinceLine.position.z += 0.2
    province.add(provinceLine)

    const coordinates = feature.geometry.coordinates
    const color1 = new THREE.Color('#1BDAFC')
    const color2 = new THREE.Color('#F3FD27')
    const color3 = new THREE.Color('#FD8B24')
    const standard1 = 2
    const standard2 = 10

    const key = province.name.replace(/省$/, '').replace(/市$/, '')
    const count = waterObj[key]

    let value
    if (count !== undefined) {
      value = waterObj[key]
    } else {
      value = 0
    }

    let lerpColor
    if (value < standard1) {
      lerpColor = color1.clone().lerp(color2, value / standard1)
    } else {
      lerpColor = color2.clone().lerp(color3, value / standard2)
    }

    if (feature.geometry.type === 'MultiPolygon') {
      coordinates.forEach(coordinate => {
        coordinate.forEach(rows => {
          const mesh = drawExtrudeMesh(rows, lerpColor)
          mesh.rotateX(Math.PI)
          province.add(mesh)
          const line = lineDraw(rows)
          line.name = '边线'
          line.position.z += 0.15
          province.add(line)
        })
      })
    }
    if (feature.geometry.type === 'Polygon') {
      coordinates.forEach(coordinate => {
        const mesh = drawExtrudeMesh(coordinate, lerpColor)
        mesh.rotateX(Math.PI)
        province.add(mesh)
        const line = lineDraw(coordinate)
        line.position.z += 0.15
        line.name = '边线'
        province.add(line)
      })
    }

    if (name) {
      const center = feature.properties.centroid
        ? feature.properties.centroid
        : feature.properties.center
      const pos = projection(center)
      province.userData.center = pos
      cityData.push({
        name: name,
        x: pos[0],
        y: -pos[1]
      })

      // 创建地图上的省份名称对象
      const provinceName = createProvinceName(pos, name)
      if (name.includes('澳门') || name.includes('香港')) return

      // 添加省份名称
      province.add(provinceName)

      // 添加光柱对象（如果存在）
      if (cylinderObj[name]) {
        province.add(cylinderObj[name])
      }

      // 存储地图数据
      province.userData.mapData = feature.geometry
    }
  })

  // 返回地图模型对象
  resolve(mapModel)
}

// 全国地图纹理
const quanGuoTexture = new THREE.TextureLoader().load(
  require('../../../../../assets/quanGuo.png')
)
quanGuoTexture.flipY = false
quanGuoTexture.repeat.set(0.00608, 0.00825)
quanGuoTexture.offset.set(0.5448, 0.549)

// 绘制模型
function drawExtrudeMesh(polygon, lerpColor) {
  const shape = new THREE.Shape()
  polygon.forEach((row, i) => {
    const [x, y] = projection(row)
    if (i === 0) {
      shape.moveTo(x, y)
    }
    shape.lineTo(x, y)
  })
  const geometry = new THREE.ExtrudeGeometry(shape, {
    depth: 10,
    bevelEnabled: true,
    bevelSegments: 10,
    bevelThickness: 0.1
  })
  const material = new THREE.MeshStandardMaterial({
    color: new THREE.Color('#00E6E6'),
    map: quanGuoTexture,
    emissiveIntensity: 0.1,
    transparent: true,
    opacity: 1
  })

  const mesh = new THREE.Mesh(geometry, [material, sideMaterial])
  mesh.texture = quanGuoTexture
  mesh.color = lerpColor
  return mesh
}

// 绘制边界线
function lineDraw(polygon) {
  const lineGeometry = new THREE.BufferGeometry()
  const pointsArray = new Array()
  polygon.forEach(row => {
    const [x, y] = projection(row)
    pointsArray.push(new THREE.Vector3(x, -y, 0))
  })
  lineGeometry.setFromPoints(pointsArray)
  const lineMaterial = new THREE.LineBasicMaterial({
    color: '#00ffff'
  })
  return new THREE.Line(lineGeometry, lineMaterial)
}

export { initMap, cityData, mapUf, projection, waterObj }
